/*
 * Copyright (C) 2022 Huawei Technologies Co., Ltd.
 * Licensed under the Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *     http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
 * PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
#ifndef SE_SERVICE_SE_SERVICE_H
#define SE_SERVICE_SE_SERVICE_H

#include "tee_defines.h"
#include "se_scp.h"

#define SE_PATH "seservice"

#define SE_ERROR      (-1)
#define SE_SUCCESS    0
#define MUTEX_SUCCESS 0

#define TA_PARAM_MAX              4
#define READER_NAME_LEN           12   /* length of "sSE_spi_0" or "eSE_spi_0" */
#define APDU_LEN_MIN              4
#define APDU_LEN_MAX              32768
#define APDU_SELECT_RESP_LEN      258U /* Initial length of buffer to receive SELECT response */
#define MAX_KEY_SIZE              256U
#define TEE_SCP03_COMMAND_MAX_LEN 255U
#define UINT16_T_MAX              0xffff

/* Copied from se_hal.h, as src can't access trustedcore include. */
/* scard_support_mode return value defines */
#define SCARD_MODE_SYNC  0
#define SCARD_MODE_SYNC2 1
#define SCARD_MODE_ASYNC 2
#define ASYNC_SLICE      10U          /* ms */
#define ASYNC_MAX_COUNT  (60U * 100U) /* total sync time = 60s */

enum reader_len {
    SCARD_INSE_LEN = 1,
    SCARD_ESE_LEN,
    SCARD_SECFLASH_LEN,
    SCARD_MSP_LEN,
    SCARD_LESE_LEN,
    SCARD_HESE_LEN,
    SCARD_MAX_LEN
};

#define SCARD_MODE_BOTH 2            /* inse&ese */
enum SE_Type {
    SCARD_MODE_INSE         = 0, /* inse */
    SCARD_MODE_ESE          = 1, /* ese */
    SCARD_MODE_SECURE_FLASH = 2, /* secure flash */
    SCARD_MODE_MSP          = 3,
    SCARD_MODE_LESE         = 4,
    SCARD_MODE_HESE         = 5,
    SCARD_MODE_MAX          = 6,
};

struct apdu_t {
    uint8_t *command_buf;
    uint32_t command_buf_len;
    uint32_t buflen;
    bool has_extended_length;
    bool has_data;
    uint8_t lc_length;
    uint8_t has_le;
    uint16_t le;
    uint8_t le_length;
    uint32_t offset;
};

enum se_commands_id {
    CMD_SESRV_CONNECT = 0x100,
    CMD_SESRV_DISCONNECT = 0x101,
    CMD_SESRV_TRANSMIT = 0x102,
    CMD_SESRV_GET_ESE_TYPE = 0x103,
    CMD_SESRV_OPEN_BASIC_CHANNEL = 0x104,
    CMD_SESRV_OPEN_LOGICAL_CHANNEL = 0x105,
    CMD_SESRV_CLOSE_CHANNEL = 0x106,
    CMD_SESRV_SELECT_CHANNEL = 0x107,
    CMD_SESRV_UNREGISTER_TA = 0x108,
    CMD_SESRV_GET_MSP_STATUS = 0x109,
    CMD_SESRV_GET_SEC_FLASH_STATUS = 0x10A,
    CMD_SESRV_SET_AID = 0x10B,
    CMD_SESRV_SET_DEACTIVE = 0x10C,
};

struct connect_msg_t {
    uint32_t reader_id;
    uint64_t p_atr;
    uint32_t atr_len;
};

struct disconnect_msg_t {
    uint32_t reader_id;
};

struct transmit_msg_t {
    uint32_t reader_id;
    uint64_t p_cmd;
    uint32_t cmd_len;
    uint64_t p_rsp;
    uint32_t rsp_len;
    uint8_t channel_id;
};

struct open_basic_channel_msg_t {
    uint32_t reader_id;
    uint64_t se_aid;
    uint32_t se_aid_len;
    uint64_t p_rsp;
    uint32_t rsp_len;
};

struct open_logical_channel_msg_t {
    uint32_t reader_id;
    uint64_t se_aid;
    uint32_t se_aid_len;
    uint64_t p_rsp;
    uint32_t rsp_len;
};

struct close_channel_msg_t {
    uint32_t reader_id;
    uint8_t channel_id;
};

struct select_channel_msg_t {
    uint32_t reader_id;
    uint64_t se_aid;
    uint32_t se_aid_len;
    uint64_t p_rsp;
    uint32_t rsp_len;
    uint8_t channel_id;
};

struct reg_ta_info_msg_t {
    uint32_t taskid;
};

struct set_aid_msg_t {
    uint64_t seaid_list;
    uint32_t seaid_list_len;
};

struct set_deactive_msg_t {
    bool deactive;
};

union se_srv_msg_data_t {
    struct connect_msg_t connect_msg;
    struct disconnect_msg_t disconnect_msg;
    struct transmit_msg_t transmit_msg;
    struct open_basic_channel_msg_t open_basic_channel_msg;
    struct open_logical_channel_msg_t open_logical_channel_msg;
    struct close_channel_msg_t close_channel_msg;
    struct select_channel_msg_t select_channel_msg;
    struct reg_ta_info_msg_t reg_ta_info_msg;
    struct set_aid_msg_t set_aid_msg;
    struct set_deactive_msg_t set_deactive_msg;
};

struct type_rsp_t {
    int type;
};

struct connect_rsp_t {
    uint32_t atr_len;
};

struct transmit_rsp_t {
    uint32_t rsp_len;
};

struct open_basic_channel_rsp_t {
    uint32_t rsp_len;
};

struct open_logical_channel_rsp_t {
    uint32_t rsp_len;
    uint8_t logic_channel_id;
};

struct select_channel_rsp_t {
    uint32_t rsp_len;
};

struct msp_status_rsp_t {
    bool msp_status;
};

struct sec_flash_status_rsp_t {
    bool sec_flash_status;
};

struct se_srv_rsp_data_t {
    TEE_Result ret;
    union {
        struct type_rsp_t type_rsp;
        struct connect_rsp_t connect_rsp;
        struct transmit_rsp_t transmit_rsp;
        struct open_basic_channel_rsp_t open_basic_channel_rsp;
        struct open_logical_channel_rsp_t open_logical_channel_rsp;
        struct select_channel_rsp_t select_channel_rsp;
        struct msp_status_rsp_t msp_status_rsp;
        struct sec_flash_status_rsp_t sec_flash_status_rsp;
    };
};

/* message header */
typedef union {
    struct {
        uint8_t     msg_class;
        uint8_t     msg_flags;
        uint16_t    msg_id;
        uint32_t    msg_size;
    } send;
    struct {
        int64_t     ret_val;
        uint32_t    msg_size;
        uint32_t    reserve;
    } reply;
} hm_msg_header;

struct se_srv_msg_t {
    hm_msg_header header;
    union se_srv_msg_data_t data;
} __attribute__((__packed__));

struct se_srv_rsp_t {
    hm_msg_header header;
    struct se_srv_rsp_data_t data;
} __attribute__((__packed__));

TEE_Result tee_srv_ipc_proc_cmd(struct se_srv_msg_t *msg_in, struct se_srv_rsp_t *rsp_in);
#endif
